import org.apache.commons.beanutils.PropertyUtils
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory

import com.thientan.controller.NhanVienController
import com.thientan.model.NhanVien
import com.thientan.model.core.AuditingInfo
import com.thientan.timer.ThienTanBackupTask

class BootStrap {
	private static final Log LOGGER = LogFactory.getLog(BootStrap.class)
	public static final String CONF_TG_CHAY = "ThoiGianChay"
	public static final String CONF_NGAY_CHAY = "NgayChay"
	public static final String CONF_T2 = "T2"
	public static final String CONF_T3 = "T3"
	public static final String CONF_T4 = "T4"
	public static final String CONF_T5 = "T5"
	public static final String CONF_T6 = "T6"
	public static final String CONF_T7 = "T7"
	
	def grailsApplication
	def init = { servletContext ->
		runTimer(servletContext)
		grailsApplication.getArtefacts("Domain").each { org.codehaus.groovy.grails.commons.GrailsDomainClass gc ->
			gc.metaClass.beforeInsert = {
				Date insertedDate = new Date()
				NhanVien nv = new NhanVienController().loggedUser
				gc.persistantProperties.findAll { it.type == AuditingInfo }.each { prop ->
					PropertyUtils.setProperty(owner.delegate, "${prop.name}",
							new AuditingInfo(ngayTao: insertedDate, nvTao: nv, ngayCapNhat: insertedDate, nvCapNhat: nv))
				}
			}

			gc.metaClass.beforeUpdate = {
				NhanVien nv = new NhanVienController().loggedUser
				gc.persistantProperties.findAll { it.type == AuditingInfo }.each { prop ->
					PropertyUtils.setProperty(owner.delegate, "${prop.name}.ngayCapNhat", new Date())
					PropertyUtils.setProperty(owner.delegate, "${prop.name}.nvCapNhat", nv)
				}
			}
		}
	}

	def destroy = {
	}

	private void runTimer(servletContext) {
		try {
			Calendar date = setupTimerArgs(servletContext)
			// By default, schedule to run every Friday afternoon at 16:30
			new Timer().schedule(new ThienTanBackupTask(), date.getTime(), 7 * 24 * 60 * 60 * 1000)
		} catch (Exception e) {
			LOGGER.error("Error when executing timer", e)
		}
	}

	private Calendar setupTimerArgs(servletContext) {
		Calendar date = Calendar.instance
		FileInputStream fis = null
		BufferedReader br = null
		try {
			String resourcePath = "${servletContext.getRealPath("")}${File.separator}conf${File.separator}application.conf"
			fis = new FileInputStream(resourcePath)
			br = new BufferedReader(new InputStreamReader(new DataInputStream(fis)))

			String strLine
			Map dbConfigInfo = [:]
			//Read File Line By Line
			while ((strLine = br.readLine()) != null)   {
				if(strLine.contains(CONF_TG_CHAY)) {
					readTimeArgs(strLine, date)
				} else if(strLine.contains(CONF_NGAY_CHAY)) {
					readWeekDayArgs(strLine, date)
				}
			}
		} catch (Exception e) {
			LOGGER.error("Error when reading configuration file", e)
		} finally {
			try {
				fis.close()
				br.close()
			} catch (Exception ex) {
				LOGGER.error("Error when closing configuration file", ex)
			}
		}
		date
	}

	private void readWeekDayArgs(String strLine, Calendar date) {
		strLine = strLine.trim()
		String weekDayStr = strLine.substring(strLine.lastIndexOf("=") + 1, strLine.length())
		int weekDay = Calendar.SUNDAY
		switch (weekDayStr) {
			case CONF_T2:
				weekDay = Calendar.MONDAY
				break
			case CONF_T3:
				weekDay = Calendar.TUESDAY
				break
			case CONF_T4:
				weekDay = Calendar.WEDNESDAY
				break
			case CONF_T5:
				weekDay = Calendar.THURSDAY
				break
			case CONF_T6:
				weekDay = Calendar.FRIDAY
				break
			case CONF_T7:
				weekDay = Calendar.SATURDAY
				break
		}
		date.set(Calendar.DAY_OF_WEEK, weekDay)
	}

	private void readTimeArgs(String strLine, Calendar date) {
		strLine = strLine.trim()
		String timeStr = strLine.substring(strLine.lastIndexOf("=") + 1, strLine.length())
		int hour = Integer.parseInt(timeStr.substring(0, 2))
		int minute = Integer.parseInt(timeStr.substring(3, 5))
		int am_pm = timeStr.substring(5, 7) == "AM" ? Calendar.AM : Calendar.PM
		date.set(Calendar.HOUR, hour)
		date.set(Calendar.MINUTE, minute)
		date.set(Calendar.SECOND, 0)
		date.set(Calendar.MILLISECOND, 0)
		date.set(Calendar.AM_PM, am_pm)
	}
}
